﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

namespace RG.Common
{
    public static class ExtentsionIEnumerable
    {
        public static List<T> ToSingleItemList<T>(this T element)
        {
            return new List<T> {element};
        }

        public static void Replace<T>(this IList<T> collection, T replaceable,T replacement)
        {
            var index = collection.IndexOf(replaceable);
            if (index == -1) return;
            collection.Remove(replaceable);
            collection.Insert(index, replacement);
        }

        public static ObservableCollection<T> ToObservableCollection<T>(this IEnumerable<T> collection)
        {
            return new ObservableCollection<T>(collection);
        }

        public static void AddRange<T>(this ObservableCollection<T> collection,IEnumerable<T> range)
        {
            var temp = range.ToList();
            temp.ForEach(collection.Add);
        }

        public static T[] Add<T>(this T[] collection,T item)
        {
            var tempList = collection.ToList();
            tempList.Add(item);
            return tempList.ToArray();
        }

        public static T[] Remove<T>(this T[] collection, T item)
        {
            var tempList = collection.ToList();
            tempList.Remove(item);
            return tempList.ToArray();
        }
    }

    public static class ExtensionDictionary
    {
        public static string GetName(this Dictionary<int, string> dic, int key)
        {
            string result;
            return dic.TryGetValue(key, out result) ? result : key.ToString();
        }
        public static int GetKey(this Dictionary<int, string> dic, string name)
        {
            return dic.Where(x => x.Value == name).Select(x => x.Key).FirstOrDefault();
        }

        #region linq-like operators for non-generics
        public static bool Contains(this IEnumerable a, object what)
        {
            foreach (var i in a)
            {
                if (i == what) return true;
            }
            return false;
        }
        public static bool Empty(this IEnumerable a)
        {
            foreach (var i in a)
            {
                return false;
            }
            return true;
        }
        public static int Count(this IEnumerable a)
        {
            int result = 0;
            foreach (var i in a)
            {
                result++;
            }
            return result;
        }

        /// <summary>
        /// Форсированное преобразование типов
        /// </summary>
        public static List<T> ToList<T>(this IEnumerable a)
        {
            var result = new List<T>();
            foreach (var i in a)
            {
                result.Add((T)i);
            }
            return result;
        }

        /// <summary>
        /// Преобразование типа T2 к базовому T1 (InvalidCastException быть не может)
        /// </summary>
        public static List<T1> ToList<T1,T2>(this IEnumerable<T2> a)
            where T2 : T1
        {
            return a.Select(i => (T1) i).ToList();
        }

        #endregion
    }

    public static class DateTimeExt
    {

        /// <summary>
        /// вертает день с которго начиналась неделя в которую входит указанная дата
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static DateTime StartOfWeek(this DateTime dt)
        {
            var diff = dt.DayOfWeek - DayOfWeek.Monday;
            if (diff < 0) diff += 7;
            return dt.AddDays(-1 * diff).Date;
        }

        /// <summary>
        /// вертает день начала и день окончания недели в которую входит указанная дата
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static DatesRange WeekFromDate(this DateTime dt)
        {
            var diff = dt.DayOfWeek - DayOfWeek.Monday;
            if (diff < 0) diff += 7;
            var startOfWeek = dt.AddDays(-1 * diff).Date;
            return new DatesRange(startOfWeek, startOfWeek.AddDays(6));
        }

    }
}
